package top.whysu.edevice.service.manage.impl;

import com.alibaba.fastjson.JSON;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import top.whysu.edevice.constant.CodeConstant;
import top.whysu.edevice.constant.DataDictionary;
import top.whysu.edevice.dao.manage.ManageDeviceDao;
import top.whysu.edevice.dao.manage.ManageVoucherDao;
import top.whysu.edevice.dto.device.DeviceAddModifyDTO;
import top.whysu.edevice.dto.device.DeviceQueryDTO;
import top.whysu.edevice.dto.manage.NodeAddDTO;
import top.whysu.edevice.dto.manage.NodeEditDTO;
import top.whysu.edevice.dto.page.PagenationDataDTO;
import top.whysu.edevice.exception.BusinessException;
import top.whysu.edevice.po.manage.ManageDevicePO;
import top.whysu.edevice.po.manage.ManageVoucherPO;
import top.whysu.edevice.service.ezviz.EzvizService;
import top.whysu.edevice.service.manage.ManageDeviceService;
import top.whysu.edevice.service.manage.ManageTreeService;
import top.whysu.edevice.service.manage.ManageVoucherService;
import top.whysu.edevice.service.system.AccountService;
import top.whysu.edevice.utils.PageUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 设备管理
 */
@Service("ManageDeviceServiceImpl")
public class ManageDeviceServiceImpl implements ManageDeviceService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ManageDeviceServiceImpl.class);

    @Resource
    private ManageDeviceDao manageDeviceDao;
    @Resource
    private AccountService accountService;
    @Resource
    private ManageVoucherDao manageVoucherDao;
    @Resource
    private ManageTreeService manageTreeService;
    @Resource
    private ManageVoucherService manageVoucherService;
    @Resource
    private EzvizService ezvizService;

    @Override
    public BigDecimal wholeAddModifyDevice(DeviceAddModifyDTO addModifyDTO) {
        // 设备id
        BigDecimal deviceId = addModifyDTO.getId();
        // 校验唯一性
        verifyUnique(addModifyDTO);
        // 校验同一凭证组下设备名称是否重复
        ManageVoucherPO manageVoucherPO = checkDeviceName(addModifyDTO.getVoucherTreeId(), addModifyDTO.getVoucherId(),
                addModifyDTO.getDeviceName(), addModifyDTO.getId());
        // 当前操作用户
        String currentUser = accountService.getCurrentLoginUser();
        if (addModifyDTO.getId() != null) {
            // 编辑
            // 先查询
            ManageDevicePO dbDevicePO = manageDeviceDao.queryById(addModifyDTO.getId());
            if (dbDevicePO == null) {
                throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "当前设备不存在！请刷新界面后重试！");
            }
            // 再更新
            BeanUtils.copyProperties(addModifyDTO, dbDevicePO);
            dbDevicePO.setUpdateTime(new Date());
            dbDevicePO.setUpdateBy(currentUser);
            manageDeviceDao.update(dbDevicePO);
            // 编辑节点
            NodeEditDTO nodeEditDTO = new NodeEditDTO();
            nodeEditDTO.setName(addModifyDTO.getDeviceName());
            nodeEditDTO.setId(dbDevicePO.getTreeId());
            manageTreeService.wholeModifyNode(nodeEditDTO);
        } else {
            // 新增
            // 需要先新增节点
            NodeAddDTO nodeAddDTO = new NodeAddDTO();
            nodeAddDTO.setPid(addModifyDTO.getTreePid());
            nodeAddDTO.setNodeType(DataDictionary.NodeType.DEVICE_TYPE);
            nodeAddDTO.setName(addModifyDTO.getDeviceName());
            BigDecimal treeId = manageTreeService.wholeAddNode(nodeAddDTO);
            if (treeId == null) {
                throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "新增节点失败！");
            }
            ManageDevicePO po = new ManageDevicePO();
            BeanUtils.copyProperties(addModifyDTO, po);
            po.setVoucherId(manageVoucherPO.getId());
            po.setTreeId(treeId);
            po.setCreateTime(new Date());
            po.setUpdateTime(new Date());
            po.setCreateBy(currentUser);
            po.setUpdateBy(currentUser);
            manageDeviceDao.insert(po);
            deviceId = po.getId();
        }
        // 在萤石增加设备
        ezvizService.createDevice(manageVoucherPO.getId(), addModifyDTO);
        // 将设备添加到凭证组下的所有账号
        ezvizService.addDeviceToAccountByVoucher(manageVoucherPO.getId(), deviceId);
        return deviceId;
    }

    @Override
    public PagenationDataDTO<ManageDevicePO> selectPage(DeviceQueryDTO deviceQueryDTO) {
        // 获取集合
        LinkedHashMap queryMap = JSON.parseObject(JSON.toJSONString(deviceQueryDTO), LinkedHashMap.class);
        // limit的起始值
        queryMap.put("rowIndex", PageUtils.getRowIndex(deviceQueryDTO.getPageNum(), deviceQueryDTO.getPageSize()));
        List<ManageDevicePO> list = manageDeviceDao.queryAllByLimit(queryMap);
        // 获取总数
        long totalSize = manageDeviceDao.count(queryMap);
        if (CollectionUtils.isNotEmpty(list) && totalSize > 0) {
            return new PagenationDataDTO<>(totalSize, deviceQueryDTO.getPageNum(), deviceQueryDTO.getPageSize(), list);
        } else {
            return PageUtils.toPagedResult(null);
        }
    }

    @Override
    public void delete(BigDecimal deviceId) {
        // 查询设备信息
        ManageDevicePO manageDevicePO = manageDeviceDao.queryById(deviceId);
        if (manageDevicePO != null) {
            // 在萤石删除设备
            ezvizService.deleteDevice(manageDevicePO);
            // 删除节点
            manageTreeService.wholeDeleteNode(manageDevicePO.getTreeId());
            // 删除设备
            manageDeviceDao.deleteById(deviceId);
        }
    }

    @Override
    public List<ManageDevicePO> getDeviceListByVoucherId(BigDecimal voucherId) {
        if (voucherId == null) {
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "凭证组id不难为空！");
        }
        ManageDevicePO queryPO = new ManageDevicePO();
        queryPO.setVoucherId(voucherId);
        return manageDeviceDao.queryAll(queryPO);
    }

    /**
     * 校验唯一性
     */
    private void verifyUnique(DeviceAddModifyDTO requestDTO) {
        // 住建id
        BigDecimal id = requestDTO.getId();
        // 设备序列号
        String deviceSerial = requestDTO.getDeviceSerial();
        // 设备名称
        String deviceName = requestDTO.getDeviceName();
        // 设备验证码
        String deviceCode = requestDTO.getDeviceCode();
        // 设备类型
        Integer deviceType = requestDTO.getDeviceType();
        // 父节点树结构id(新增的时候使用)
        BigDecimal treePid = requestDTO.getTreePid();
        // 如果是摄像机
        if (DataDictionary.DeviceType.IPC == deviceType) {
            if (StringUtils.isBlank(deviceSerial) || StringUtils.isBlank(deviceName) || StringUtils.isBlank(deviceCode)) {
                throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "设备序列号/设备名称/设备验证码不能为空！");
            }
        } else if (DataDictionary.DeviceType.COLLECT == deviceType) {
            if (StringUtils.isBlank(deviceName)) {
                throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "设备名称不能为空！");
            }
        }
        if (id == null) {
            // 新增的情况下，treePid不能为空
            if (treePid == null) {
                throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "树结构父节点id不能为空！");
            }
        }
    }

    /**
     * 查询当前凭证组下是否存在同名的设备（新增、修改的情况共同判断）
     *
     * @param voucherTreeId 凭证组树结构id(新增的时候使用)
     * @param voucherId     凭证组id(编辑的时候使用)
     * @param deviceName    设备名称
     * @param deviceId      设备id，指的是e_manage_device的主键id
     * @return 凭证组信息
     */
    private ManageVoucherPO checkDeviceName(BigDecimal voucherTreeId, BigDecimal voucherId, String deviceName, BigDecimal deviceId) {
        if (deviceId == null) {
            // 新增的情况下，凭证组树结构id不能为空
            if (voucherTreeId == null) {
                throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "新增情况下凭证组树结构id不能为空！");
            }
            // 根据树结构id查询凭证组信息
            ManageVoucherPO manageVoucherPO = manageVoucherService.getVoucherByTreeId(voucherTreeId);
            if (manageVoucherPO == null) {
                throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "凭证组不存在！请刷新界面后重试！");
            }
            // 校验同一凭证组下名称是否重复
            checkName(manageVoucherPO.getId(), deviceName, null);
            return manageVoucherPO;
        } else {
            // 编辑的情况下，凭证组id不能为空
            if (voucherId == null) {
                throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "编辑情况下凭证组id不能为空！");
            }
            // 根据树结构id查询凭证组信息
            ManageVoucherPO manageVoucherPO = manageVoucherDao.queryById(voucherId);
            if (manageVoucherPO == null) {
                throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "凭证组不存在！请刷新界面后重试！");
            }
            // 校验同一凭证组下名称是否重复
            checkName(voucherId, deviceName, deviceId);
            return manageVoucherPO;
        }
    }

    /**
     * 校验同一凭证组下名称是否重复
     *
     * @param voucherId  凭证组id
     * @param deviceName 设备名称
     * @param deviceId   设备主键id，指的是e_manage_device的主键id
     */
    private void checkName(BigDecimal voucherId, String deviceName, BigDecimal deviceId) {
        ManageDevicePO queryPO = new ManageDevicePO();
        queryPO.setVoucherId(voucherId);
        queryPO.setDeviceName(deviceName);
        List<ManageDevicePO> deviceList = manageDeviceDao.queryAll(queryPO);
        if (CollectionUtils.isNotEmpty(deviceList)) {
            if (deviceId == null) {
                throw new BusinessException(CodeConstant.Http.DEVICE_ALREAY_EXIST, "当前凭证组下该设备名称已被使用，请重命名！");
            } else {
                deviceList.forEach(it -> {
                    if (!it.getId().equals(deviceId)) {
                        throw new BusinessException(CodeConstant.Http.DEVICE_ALREAY_EXIST, "当前凭证组下该设备名称已被使用，请重命名！");
                    }
                });
            }
        }
    }
}